/* Copyright  2009
   @Author
   Richard Changde Yin            e-mail yinchangde@hotmail.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/**
 * @filename: transaction.h
 */

#ifndef __TXN_H__
#define __TXN_H__

#include <os.h>
#include <debug.h>
#include <session.h>

/**
* @enum IsolationLevel
* @brief Represents isolation level of the transaction.
*/
enum IsolationLevel
{
    READ_UNCOMMITTED = 1,
    READ_COMMITTED = 2,
    READ_REPEATABLE = 3,
    WRITE_OSYNC = 4 //this will work only from sqlapi
                    //for dbapi WRITE_OSYNC = READ_REPEATABLE
};

class LockHashNode;

enum TransStatus
{
    TransNotUsed          =  0,
    TransCommitting       =  1,
    TransAborting         =  2,
    TransRunning          =  3,
    TransUnknown          =  4
};
class TransHashNode;
class LockManager;
class Database;

enum OperationType
{
    InsertOperation          = 0,
    DeleteOperation          = 1,
    UpdateOperation          = 2,
    InsertHashIndexOperation = 3,
    UpdateHashIndexOperation = 4,
    DeleteHashIndexOperation = 5,
    UnkownOperation          = 6
};
class UndoLogInfo
{
   UndoLogInfo& operator = (UndoLogInfo&);
   UndoLogInfo(UndoLogInfo&);
public:

    UndoLogInfo():size_(-1),
                  opType_(UnkownOperation),
                  ptrToTuple_(0),
                  next_(0)
    {}
    virtual ~UndoLogInfo(){}

    int size_;

    OperationType opType_;

    void *ptrToTuple_;

    UndoLogInfo *next_;

    inline void print() {
    }
};

class HashUndoLogInfo
{
    HashUndoLogInfo& operator =(const HashUndoLogInfo&);
    HashUndoLogInfo (const HashUndoLogInfo&);
public:
    void *tblPtr_;
    void *tuple_;
    void *keyPtr_;
    void *indexPtr_;
    void *bucket_;
    HashUndoLogInfo():tblPtr_(NULL),
                      tuple_ (NULL),
                      keyPtr_(NULL),
                      indexPtr_ (NULL),
                      bucket_ (NULL)
    {}
};

class Transaction
{
    Transaction& operator = (Transaction&);
    Transaction (const Transaction&);
    Transaction (Transaction&);
public:

    Transaction(): status_(-1),
                   hasLockList_(0),
                   tailLockList_(0),
                   firstUndoLog_(0),
                   waitLock_(0){}
    int status_;

    IsolationLevel isoLevel_;

    TransHashNode   *hasLockList_;

    TransHashNode   *tailLockList_;

    UndoLogInfo    *firstUndoLog_;

    LockHashNode   *waitLock_;

    BackEnd::DbRetVal releaseAllLocks(LockManager *lockManager_);

    inline void updateWaitLock(LockHashNode *node) { waitLock_ = node; }

    inline void removeWaitLock() { waitLock_ = NULL; }

    BackEnd::DbRetVal insertIntoHashList(Database *sysdb, LockHashNode *node);

    BackEnd::DbRetVal removeFromHashList(Database *sysdb, void *tuple);

    bool findInHashList(Database *sysdb, LockHashNode *node);

    BackEnd::DbRetVal appendUndoLog(Database *sysdb, OperationType type,
                           void *data, size_t size);
    BackEnd::DbRetVal appendLogicalUndoLog(Database *sysdb, OperationType type,
                                  void *data, size_t size, void *indexPtr);
    BackEnd::DbRetVal appendLogicalHashUndoLog(Database *sysdb,
                                               OperationType type,
                                               void *data, size_t size);
    UndoLogInfo* createUndoLog(Database *sysdb,
                               OperationType type,
                               void *data,
                               size_t size, BackEnd::DbRetVal *rv);
    void addAtBegin(UndoLogInfo* logInfo);

    UndoLogInfo* popUndoLog();

    BackEnd::DbRetVal removeUndoLogs(Database *sysdb);
    BackEnd::DbRetVal applyUndoLogs(Database *sysdb);

    int noOfUndoLogs();
    void printDebugInfo(Database *sysdb);
};
/// The TransactionManager
class TransactionManager
{
public:
    TransactionManager() {  }

    virtual ~TransactionManager() {}

    Transaction *firstTrans;

    void setFirstTrans(Transaction *trans);

    void printUsageStatistics();

    void printDebugInfo(Database *sysdb);

    BackEnd::DbRetVal startTransaction(LockManager *lManager,
                                       IsolationLevel level);
    BackEnd::DbRetVal commit(LockManager *lManager);

    BackEnd::DbRetVal rollback(LockManager *lManager,
                               Transaction *t=NULL);

};
#endif //__TXN_H__
